﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;


namespace ElPrimeroElMejor
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        Distancias d = new Distancias();

        List<NodoPrimeroMejor> Abiertos = new List<NodoPrimeroMejor>();
        List<NodoPrimeroMejor> Cerrados = new List<NodoPrimeroMejor>();
        

        #region Metodos

        public void Solucion()
        {
            

        //Genero los nodos abiertos a partir del origen
            for (int i = 0; i <= 6; i++)
            {
                if (d.DevuelveDistancia(0, i) != 0)
                {
                    NodoPrimeroMejor nuevoNodo = new NodoPrimeroMejor();
                    nuevoNodo.DistanciaAcumulada = d.DevuelveDistancia(0, i);
                    nuevoNodo.Predecesor = 0;
                    nuevoNodo.NodoActual = i;

                    Abiertos.Add(nuevoNodo);
                    txtAbiertos.Text=MuestraNodos(Abiertos);
                    txtCerrados.Text = MuestraNodos(Cerrados);
                }
            }

            //do
            //{
            //    //Elijo el más prometedor, lo agrego a Cerrados y quito de Abiertos
            //    Cerrados.Add(MasPrometedor(Abiertos));
            //    Abiertos.Remove(MasPrometedor(Abiertos));

            //    //Expando nodos desde ese más prometedor
            //    Expandir(Cerrados[Cerrados.Count - 1]);

            //} while (Cerrados[Cerrados.Count - 1].NodoActual != 6);

            //txtSolucion.Text = "Distancia mínima: 16. \r\n";
            //txtSolucion.Text+= "Nodos recorridos:\n";

            //MuestraCamino();
            
        }

        public NodoPrimeroMejor MasPrometedor(List<NodoPrimeroMejor> l)
        {
            NodoPrimeroMejor aux = new NodoPrimeroMejor();
            aux = l[0];
            foreach (NodoPrimeroMejor n in l)
            {
                if (n.DistanciaAcumulada < aux.DistanciaAcumulada)
                    aux = n;
            }

            return aux;
        }

        public void Expandir(NodoPrimeroMejor n)
        {
            for (int i = 0; i <= 6; i++)
            {
                if (d.DevuelveDistancia(n.NodoActual, i) != 0 && Etiquetado(i) == false)
                {
                    NodoPrimeroMejor nuevoNodo = new NodoPrimeroMejor();
                    nuevoNodo.DistanciaAcumulada = n.DistanciaAcumulada + d.DevuelveDistancia(n.NodoActual, i);
                    nuevoNodo.Predecesor = n.NodoActual;
                    nuevoNodo.NodoActual = i;
                    //Me aseguro de quedarme en Abiertos con el camino más corto a ese nodo
                    NodoPrimeroMejor aux = new NodoPrimeroMejor();
                    aux = null;
                    foreach(NodoPrimeroMejor h in Abiertos)
                    {
                        if (h.NodoActual == nuevoNodo.NodoActual)
                        {
                            aux = h;
                            break;
                        }
                    }
                    if (aux == null)
                    {
                        Abiertos.Add(nuevoNodo);
                    }
                    else
                    {
                        if (nuevoNodo.DistanciaAcumulada < aux.DistanciaAcumulada)
                        {
                            Abiertos.Add(nuevoNodo);
                            Abiertos.Remove(aux);
                        } 
                        
                    }
                    //Abiertos.Add(nuevoNodo);
                }
            }
        }

        public Boolean Etiquetado(int j)
        {
            foreach (NodoPrimeroMejor n in Cerrados)
            {
                if (n.NodoActual == j)
                    return true;
            }

            if (j == 0)
                return true;
            else
                return false;
        }

        public void MuestraCamino()
        {
            List<int> camino = new List<int>();
            NodoPrimeroMejor aux = new NodoPrimeroMejor();
            aux = Cerrados[Cerrados.Count - 1];
            do
            {
                camino.Add(aux.NodoActual);
                foreach (NodoPrimeroMejor n in Cerrados)
                {
                    if (aux.Predecesor == n.NodoActual)
                    {
                        aux = n;
                        //break;
                    }
                }
            } while (aux.Predecesor != 0);
            camino.Add(aux.NodoActual);
            camino.Add(aux.Predecesor);

            for(int i=camino.Count-1;i>=0;i--)
                txtSolucion.Text += camino[i].ToString()+"\n";

        }

        public string MuestraNodos(List<NodoPrimeroMejor> lista)
        {
            string aux="";
            if (lista.Count != 0)
            {
                foreach (NodoPrimeroMejor n in lista)
                {
                    aux += "(" + n.DistanciaAcumulada + "," + n.Predecesor + "," + n.NodoActual + ")" + "\r\n";
                }
                return aux;
            }
            else
                return "";
            
        }

        #endregion

        #region Eventos

        private void salirToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void enunciadoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string enunciado = "El siguiente problema consiste en el enrutamiento de un paquete desde un host origen "+
                                "a un host destino, pasando por routers intermedios, de forma tal "+
                                "que se minimice el retardo total.";

            MessageBox.Show(enunciado, "Enunciado", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        private void primeroElMejorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string info = "EL PRIMERO EL MEJOR \n\n" +
                "Despues lo busco. \n\n" +
                "Fuente:  ";

            MessageBox.Show(info, "Ayuda", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        #endregion

        private void btnSiguiente_Click(object sender, EventArgs e)
        {

            if (Cerrados.Count==0 || Cerrados[Cerrados.Count - 1].NodoActual != 6)
            {
                //Elijo el más prometedor, lo agrego a Cerrados y quito de Abiertos
                Cerrados.Add(MasPrometedor(Abiertos));
                Abiertos.Remove(MasPrometedor(Abiertos));

                //Expando nodos desde ese más prometedor
                Expandir(Cerrados[Cerrados.Count - 1]);
                txtAbiertos.Clear();
                txtAbiertos.Text = MuestraNodos(Abiertos);
                txtCerrados.Clear();
                txtCerrados.Text = MuestraNodos(Cerrados);
            }

            else
            {
                txtSolucion.Text = "Distancia mínima: 16. \r\n";
                txtSolucion.Text += "Nodos recorridos:\n";

                MuestraCamino();
                picBoxProblema.Image = ElPrimeroElMejor.Properties.Resources.RedResuelta;
            }  

        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            Solucion();
            btnSiguiente.Enabled = true;
            button1.Enabled = false;
            btnReiniciar.Enabled = true;
        }

        private void btnReiniciar_Click(object sender, EventArgs e)
        {
            Abiertos.Clear();
            Cerrados.Clear();
            txtAbiertos.Clear();
            txtCerrados.Clear();
            txtSolucion.Clear();
            picBoxProblema.Image = ElPrimeroElMejor.Properties.Resources.Red;
            Solucion();
        }
    }
}
